

Isetta programming manual
-------------------------

 3-1-2025 started
10-1-2025 updated
11-1-2025 new blitter codes
 9-2-2025 debugger function working
12-3-2025 manual published on hackaday.io page
20-3-2025 added copycnv to blitter
 6-5-2025 blitter remarks
 9-6-2025 add sound system
 1-7-2025 changed blitter port values
24-11-2025 update


Chapter 1  I/O ports
Chapter 2  Video system
Chapter 3  Blitter
Chapter 4  Sound system
Chapter 5  Debugger support



Chapter 1  I/O ports
--------------------

Just as in the Z80 and 8080, Isetta can input or output a single byte at I/O ports. There are 256 possible
ports for input and 256 for output. An I/O instruction is two bytes long:

  <0xD3><portnumber>   OUT instruction: This will output the byte in ACC to the specified port number

  <0xDB><portnumber>   IN instruction: This will input a byte from the specified port number and put it in ACC.

In Isetta, these IN and OUT instructions are also in the 6502 instruction set, with the same opcodes 0xD3 and 0xDB.

Using undefined I/O port numbers will, in the current version, most likely result in a crash.


I/O ports - general
-------------------

port_in_config   =  0xE4;  // INPUT this tells what the HW configuration is. For the current version, always zero.

port_in_microcode_year =  0xE6  ; // INPUT reads the microcode date from microcode flash (reads from flash page 6).
port_in_microcode_month = 0xE7  ;
port_in_microcode_day =   0xE8  ;

port_out_isa_6502 = 0x0A;  // OUTPUT switch instruction set to 6502. Preserves Accumulator and PC.

port_out_isa_Z80  = 0x0B;  // OUTPUT switch instruction set to Z80. Preserves Accumulator and PC.	

Instead of switching instruction set with writing an arbitrary value to the above ports, it is also
possible to write to "port_io_reg_isa" with the ISA number in ACC. Reading from this port gives
the current ISA. 

port_io_reg_isa = 0x10;

Supported values for port_io_reg_isa are:
  const ISA_6502 = 0x38;
  const ISA_Z80  = 0x39; 
  // 0x3A;  // used by Blitter
  // 0x3B;  // used by Sound generator

To terminate your user program, you can write a value to port_out_shutdn.
  value 00: Isetta will reset
  value 01: Isetta will shut down. Power LED and screen switch off. 
            (But the board and chips still have power, RTC keeps running)
            Use the button at the front, or reset-button to power-up again.

port_out_shutdn  = 0x1C


I/O ports - memory banks and bankswitching
------------------------------------------

The Isetta computer has either 512kB or 1024 kB memory.

There are 8 or 16 memory banks (of 64kByte each) in RAM. Each bank has 4 blocks of 16 kByte.
In this section, the hardware bank numbers are used. Software may define bank numbers different.
After startup, your Z80 or 6502 program will normally run in HW bank 3.

Use of the memory banks:

  HW bank 0    system data, Hires screen buffer (upper screen half)
  HW bank 1    system data, partially free to use (see below) (SymbOS bank6)
  HW bank 2    system data, Hires screen buffer (lower screen half)
  HW bank 3    Main Z80/6502 bank (SymbOS bank0)
  HW bank 4    free to use  (SymbOS bank1)
  HW bank 5    free to use  (SymbOS bank2)
  HW bank 6    free to use  (SymbOS bank3)
  HW bank 7    free to use  (SymbOS bank4)
  HW bank 8-15 free to use  (SymbOS bank 8-15) (for Isetta's with 1024 kB memory) 

Transfer a single byte to/from another bank:

port_io_bank0 = 0xF0  // IN/OUT read/write byte (in ACC) from/to memory location (in HL) in HW bank0.
port_io_bank1 = 0xF1  // same for HW bank1
port_io_bank2 = 0xF2  // same for HW bank2	
port_io_bank3 = 0xF3  // same for HW bank3


In general, all memory in HW banks 3 - 15 are free for use by a user program or operating system.
However, in HW bank1 there are two ranges that can also be used:
  - 0x0000 - 0x03FF  (not useable for 6502)
  - 0xMM00 - 0xFFFF  The value MM is obtained by reading the input port_in_bnk1_free:

port_in_bnk1_free = 0x27   (The obtained value can be different, depending on the microcode version)

For bankswitching, write a value (in A) to port_out_sbnk:

port_out_sbnk  = 0x1B;  // OUTPUT  set bank configuration according to register A.

The possible values are:

         A = 11000000 ;  // The Z80/6502 only sees HW bank 3 (this is the default). (C0)
         A = 1NBBB010 ;  // The Z80/6502 only sees the memory bank according to NBBB (see table). (C2)
         A = 1NBBB1LL ;  // The Z80/6502 only sees bank 3, but in the range 0x4000 - 0x7FFF it sees
		         // block number LL from the memory bank selected with NBBB (see table). (C4-7)
         A = 1NBBB001 ;  // The Z80/6502 only sees bank 3, but in the range 0xC000 - 0xFFFF it sees
			 // block number 3 from the memory bank selected with NBBB (see table). But it can not
			 // execute from that block. (C1)

table: NBBB                LL
       1000  HW bank 4     00 block 0 (0x0000-0x3FFF)
       1001  HW bank 5     01 block 1 (0x4000-0x7FFF)
       1010  HW bank 6     10 block 2 (0x8000-0xBFFF)
       1011  HW bank 7     11 block 3 (0xC000-0xFFFF)
       1100  HW bank 0
       1101  HW bank 1
       1110  HW bank 2
       1111  HW bank 3
       0xxx  HW bank 8 - 15 (for Isetta's with 1024 kB memory) 

In older versions, bankswitching had to be enabled as follows:

port_out_system  = 0x18;   // OUTPUT default is 0x00. Set it to 0x40 to enable bankswitching.

Instruction for bankswitch and jump: 4 byte-instruction  D3 1E 34 12 will do bankswitch according
 to register A and jump to #1234. (So it is an OUT instruction).

todo:  - output to set HL register (6502)
       - have bankswitch instruction for 6502



I/O ports - Character I/O and Mouse
-----------------------------------

port_in_scancode = 0x31; // IN read PS/2 keyboard scancode (bits reversed) or byte from RPi.
                         // This input reads from a 256 byte buffer.
                         // Returns ACC=zero if the buffer is empty.

port_out_tx      = 0x31; // (no longer used) OUT sends a byte to the RPi. RPi has to provide the clock.
                         // if ACC=0 after this instruction, the buffer was full and the OUT must be retried.

port_in_mouse    = 0x32; // IN receive a byte from the PS/2 mouse (bits reversed). 
                         // This input reads from a 256 byte buffer.
                         // Returns Z=1 if the buffer was empty.

Information about the PS/2 protocol can be found here:
https://www.eecg.utoronto.ca/~jayar/ece241_08F/AudioVideoCores/ps2/ps2.html
The mouse must be enabled by giving it a 0xF4 command, Isetta does that always at start-up.
Several PS/2 keyboards must also be enabled, Isetta does that also at startup.


I/O ports - SPI functions
-------------------------

port_spi1_start = 0x32;  // OUT start transaction on SPI-1
port_spi2_start = 0x33;  // OUT start transaction on SPI-2
port_spi_out    = 0x37;  // OUT send byte (in ACC) to SPI device
port_spi_in     = 0x3A;  // IN read byte from SPI device to ACC
port_spi_idle   = 0x3F;  // OUT stop transaction
port_spi_state  = 0x3C;  // IN read status byte from SPI. Sets Z flag if SPI active.


Note 1) spi1_start has the same port number as in_mouse. But since the first one is output and
 the other one input, there is no conflict.

Note 2) While a SPI transaction is in progress, the RST #38 interrupts are disabled (by microcode).


I/O ports - Sound
-----------------

port_out_sound = 0x30;   // OUT  output a byte to the sound_output/general output. Effective at next scanline interrupt.
							

I/O ports - ZX Spectrum specific
---------------------------------

port_io_zx_spectrum = 0xFE  // IN/OUT
port_io_zx_joystick = 0x1F  // IN reserved for joystick. Unused.

port_io_zx_128      = 0xFD  // reserved for OUT, ZX_Spectrum 128 paging system


I/O ports - Real time clock
---------------------------

There are two clock functions. Both need, in HL, a pointer to the following structure:

t_sec   db 0    ;0 - 59
t_min   db 0    ;0 - 59
t_hour  db 0    ;0 - 23
t_day   db 1    ;1 - 28,29,30 or 31
t_month db 1    ;1 - 12
t_year  db 0,20 ;0-99 in first byte, 20 in second byte
t_magic db 0    ; 0xA3

The first function retrieves the current time and date. Load HL with the address where you want the values to
be placed, then do an input from port "port_io_rtc_read". If t_magic is 0xA3, this indicates that the time
has been initialized to a valid value.

port_io_rtc_read = 0xCC  ; use IN for read

The second function sets the clock to a new time and date. Load HL with the address where the values are,
then do an output to port "port_io_rtc_write". (t_magic should be 0xA3)

port_io_rtc_write = 0xCC ; use OUT for write

Note that the accumulator is not used in the time I/O functions.


Chapter 2  Video system
-----------------------

The video system uses a "frame table" that describes what should happen at every scanline. There are 525 scanlines
in a normal VGA screen (400 or 480 visible), so the table is 525 bytes long. The microcode part that writes
to the screen will read a action-code byte from this table at the start of each scanline, and that byte
determines the action that the microcode will execute. 

Frame table location: 0x0700 in HW bank 1.

possible actioncodes:

v_prepare     equ $24  ; At very first frame table location. Initializes for the visible scanlines that follow.
v_end         equ $25  ; This has to follow the last visible scanline
v_blank       equ $26  ; This is a line in blanking period. Almost all time in these lines is used for Z80/6502 processing.
v_wait        equ $27  ; This must be in the line just before changing the vertical sync signal
v_act_vsync   equ $2A  ; At this line, vertical sync is activated
v_deact_vsync equ $2B  ; At this line, vertical sync is de-activated
v_repeat      equ $2C  ; At the end of the frame table, causes a jump back to the start of the frame table

And here are the actioncodes that define the video mode at each visible scanline:

v_hires       equ $2D  ; This causes a line of high-resolution video to be written to the screen
v_spectrum    equ $0D  ; This causes a line of ZX-spectrum video to be written to the screen
v_pix_320     equ $34  ; This causes a line of 320 pixels to be written to the screen

Instead of a v_blank, a sound processing code can be used:

v_sound       equ $64  ; This causes the sound processor to produce a series of 256 samples (if enough space in buffer)

In general, the codes for the video mode also refer to a video line and attribute line: (example for line n)

   0x0700 + n  (HW bank1)  ; this byte has the action code   
   0x0300 + n  (HW bank0)  ; this byte has the LSB of the video line data address
   0x0300 + n  (HW bank2)  ; this byte has the MSB of the video line data address
   0x0300 + n  (HW bank1)  ; this byte has, for ZX spectrum mode, the MSB of the video attribute line.


Hires video mode
----------------

The hires mode has a resolution of 640 x 400 pixels, with 16 colors for every pixel.

For the hires mode, the video line is 320 bytes long. Each byte has a first pixel in the high nibble, and a second 
pixel in the low nibble, so the video line is 640 pixels long.
The screen is divided in the upper half and the lower half.
For the upper half, the video lines are in HW bank 0 starting at 0x0600, up to 0xFFFF (200 upper half lines).
For the lower half, the video lines are in HW bank 2 starting at 0x0600, up to 0xFFFF (200 lower half lines).

So, the video data is almost 128 kBytes.
Since the video line address is 17 bits, it is stored in a special way in the table.
Supposing that the address is always even, it is shifted one bit to the right. The upper bit is
then filled with a "0" if it is in the upper half and a "1" if it is in the lower half of the screen.

The pixel color in the nibble is defined as "DRGB", where R,G,B bits define if the R,G,B components are each on or off. The
"D" bit will, if set to 1, result in a dark version of the specified color.

Note that, since the start address of each video line is in the frame table, scrolling up or down can be very fast, since only
the start addresses have to be changed in the table. Horizontal scrolling can also be very quick.


320 pixel video mode
--------------------

This mode has a resolution of 320 x 200 pixels, with 64 colors for every pixel.
This is not tested yet.


ZX Spectrum video mode
----------------------

The ZX spectrum video mode has a resolution of 256 x 192 pixels with 2 colors. For each block of 8 x 8 pixels there
is an attribute byte, that defines the 2 possible colors for these 64 pixels.

Each video line is located in the normal addressing range of the processor (HW bank 3), starting at 0x4000 (up to 0x57FF).
Each line is 32 bytes long, with 8 pixels per byte this defines the 256 pixels of a line.
The starting address of a video line is in the frame table as described before. 

The attribute bytes, also 32 bytes per line, are also in the normal addressing range of the processor, starting at 0x5800 (up to 0x5AFF).
The LSB of the address of this attribute byte is the same as the LSB of the pixel data. The MSB of the  
attribute byte is at location "0x0600 + n  (bank1)" as described above.

The layout of the video lines in memory is not straightforward, you can find it here: (also describes how color is encoded)
http://www.breakintoprogram.co.uk/hardware/computers/zx-spectrum/screen-memory-layout

The flashing of video data is not implemented (yet?).



Chapter 3  Blitter
------------------

The Blitter is a microcoded unit that is specialized in writing to rectangular sections of the Hires screen.
To use this, you first setup the parameters, using special OUTPUT ports. After that, you start the blitter by
writing the action code to the P_BLITCTRL output port. 

Most commands require three kinds of parameters:  (most parameters are 16 bits)
 - source base address, coordinates, line-length
 - screen coordinates
 - rectangle size
A few commands use FILL1 and FILL2 that both specify a color.


Blitter color conversion
------------------------

With the action code D_BMCOPYCNV "copy-convert" (see action codes), the blitter will convert
colors from the SymbOS numbering (used in memory) to the Isetta numbering (used on the screen).

Isetta colors:
0  black
1  blue
2  green
3  cyan
4  red
5  magenta
6  yellow
7  white
15 gray
8  dark  // add this to the basic color number (except gray) to get a dark version

SymbOS colors:
0  light yellow (no correct conversion possible)
1  black                        
2  orange       (no correct conversion possible)
3  dark red
4  cyan
5  dark blue                 
6  light blue   (converted to cyan)
7  blue
8  white
9  dark green
10 green
11 magenta
12 yellow
13 gray
14 light red    (no correct conversion possible)
15 red



Blitter Source parameters port numbers (SRC)
--------------------------------------------

The source parameters can refer to a position in memory, or to a position on the screen.

P_BLITSRCX_L equ #90 ; src_x_l  X-coordinate (in pixels)
P_BLITSRCX_H equ #91 ; src_x_h
P_BLITSRCY_L equ #92 ; src_y_l  Y-coordinate (in pixels)
P_BLITSRCY_H equ #93 ; src_y_h

P_BLITSRCA_L equ #B7 ; src_a_l  Base address (24 bits)
P_BLITSRCA_H equ #B8 ; src_a_h
P_BLITSRCA_U equ #B9 ; src_a_u  (upper byte of base address)

P_BLITSRCL_L equ #BA ; src_l_l  line length (bytes)
P_BLITSRCL_H equ #BB ; src_l_h

/* old values were:
P_BLITSRCA_L equ #97 ; src_a_l  Base address (24 bits)
P_BLITSRCA_H equ #98 ; src_a_h
P_BLITSRCA_U equ #9A ; src_a_u  (upper byte of base address)

P_BLITSRCL_L equ #9B ; src_l_l  line length (bytes)
P_BLITSRCL_H equ #9F ; src_l_h
*/

When the source is memory, Y-coordinate should be zero. The base address should be set, and
src_a_u should be a value 0 - 7, where the value 0 is HW bank3, value 1 is HW bank4, etc (wrapping around).
The source rectangle should be fully inside a single HW bank.
The line length gives the number of bytes to be added to go to the next source line.
For writing TEXT from a 8x8 font (where each byte represents a character row), the line length
should be set to 1.

When the source is a screen address, X and Y give the pixel coordinates, and
the 24-bit address should be 0x800600 (The upper bit indicates that a screen address is used).
The HW bank is selected automatically (screen rectangle can be partially on upper and lower screen half).
The line length should be 320 (number of bytes to go to next line)

When the action is D_BMFILL or D_BMFXOR, the source parameters are not needed, but src_x_l must be set to 0.


Blitter Screen parameters port numbers (DST)
--------------------------------------------

P_BLITDSTX_L equ #88 ; dst_x_l  X-coordinate (in pixels)
P_BLITDSTX_H equ #89 ; dst_x_h
P_BLITDSTY_L equ #8A ; dst_y_l  Y-coordinate (in pixels)
P_BLITDSTY_H equ #8B ; dst_y_h

/* old values were:
P_BLITDSTX_L equ #A0 ; dst_x_l  X-coordinate (in pixels)
P_BLITDSTX_H equ #A1 ; dst_x_h
P_BLITDSTY_L equ #A2 ; dst_y_l  Y-coordinate (in pixels)
P_BLITDSTY_H equ #A3 ; dst_y_h 
*/

This is always a position on the Hires screen. The upper left pixel has
coordinates (0,0). Screen contents is 4bpp (bits per pixel).


Blitter Size parameters port numbers
------------------------------------

P_BLITSIZX_L equ #B0 ; size_x_l  rectangle X-size in pixels
P_BLITSIZX_H equ #B1 ; size_x_h
P_BLITSIZY_L equ #B2 ; size_y_l  rectangle Y-size in pixels
P_BLITSIZY_H equ #B3 ; size_y_h


Blitter Fill parameters port numbers
------------------------------------

P_BLITFILL1 equ #78 ; fill1 (4 bits) (also text foreground color). Use the SymbOs color numbers.
P_BLITFILL2 equ #79 ; fill2 (4 bits) (also text background color). Use the SymbOs color numbers.


Blitter Starting action
-----------------------

There are several actions that the blitter can perform, they are started by writing the action code 
to the control port. The blitter will then take control, and after the operation is completed, control is
given back to the Z80/6502 processor.

P_BLITCTRL equ #EA ; port number for blitter control port


Blitter Action codes
--------------------

D_BMCOPY equ #08 ; COPY source to screen
D_BMCOPYCNV equ #00 ; COPY source to screen, converting SymbOs colors to Isetta colors
D_BMSKIP equ #04 ; As COPYCNV, but SymbOs color 0 is transparent
D_BMSAVE equ #01 ; Save from screen to source memory address
D_BMTEXT equ #09 ; TEXT write a character from a font map to the screen. Font map is 1bpp.
D_BMFILL equ #2D ; Fill a screen rectangle, alternating colors FILL1 and FILL2
D_BMFXOR equ #2E ; Fill a screen rectangle using XOR operator, alternating colors FILL1 and FILL2

The following modifier codes can be added to the action code:

D_BLITBACKX equ #0B ; Only for COPY. Action is performed right-to-left. (not implemented)
D_BLITBACKY equ #80 ; Only for COPY. Action is performed bottom-to-top.

D_BLITP14 equ #00 ; Only used with TEXT. Converts 1bpp to 4 bpp (bits per pixel)
D_BLITP24 equ #02 ; Only used with COPYCNV or SKIP. Converts 2bpp to 4 bpp
D_BLITP44 equ #00 ; Default, screen and source are both 4bpp

After the action the blitter will add size_x_l to dst_x. So, after writing a character
it is not needed to set the screen-x-coordinate to the next position.

For 2bpp to 4bpp conversion:
  - 00 converts to 0000 (black)
  - 01 converts to FILL2
  - 10 converts to FILL1
  - 11 converts to FILL1 XOR FILL2

NOTE When D_BLITBACKY is used, the Y coordinates of src and dst must be the bottom coordinates.
    The blitter will decrement the Y coordinate after every processed line.

NOTE (6-5-2025) before using COPYCNV you must put color 0 (lightyellow) in FILL1.

NOTE (3-1-2025) The blitter doesn't work for 6502 yet.

NOTE (23-4-2025) The 2bpp functions do not yet work correctly when src and dst are not well aligned

NOTE (15-5-2025) The parameters are internally stored in registers similar to BC, DE, HL. But when
     an EXX swap is used after filling parameters, the parameters are also swapped, and the blitter 
     action finds wrong parameter values. So better not use odd number of EXX between setting 
     parameters and doing the action.

NOTE The blitter only works if the bankswitching system is enabled.


Chapter 4  Sound system
-----------------------

Isetta has a sound system that is compatible with the PSG (programmable sound generator) AY-3-8910.

The PSG has three channels, that each can generate a tone or noise, with adjustable volume each.

The PSG has several 8-bit registers, R0 - R15. First write the register number 
to port_out_psg_reg, then write the data for that register to port_out_psg_data.
It is not possible to read from a register.

port_out_psg_reg  equ 0x40 ; port number for PSG register

port_out_psg_data equ 0x41 ; port number for PSG data


    Registers:
   
        7654 3210
    R0  PPPP PPPP  Channel A tone period  7..0.
    R1  ---- PPPP  Channel A tone period 11..8.
    R2  PPPP PPPP  Channel B tone period  7..0.
    R3  ---- PPPP  Channel B tone period 11..8.
    R4  PPPP PPPP  Channel C tone period  7..0.
    R5  ---- PPPP  Channel C tone period 11..8.
    R6  ---P PPPP  Noise shift period.
    R7  I--- ----  unused
        -I-- ----  unused
        --C- ----  Mix Noise with Channel C, active low.
        ---B ----  Mix Noise with Channel B, active low.
        ---- A---  Mix Noise with Channel A, active low.
        ---- -C--  Enable Channel C, active low.
        ---- --B-  Enable Channel B, active low.
        ---- ---A  Enable Channel A, active low.
    R8  ---M ----  Channel A Mode, 0=level, 1=envelope.
        ---- LLLL  Channel A Level.
    R9  ---M ----  Channel B Mode, 0=level, 1=envelope.
        ---- LLLL  Channel B Level.
    R10 ---M ----  Channel C Mode, 0=level, 1=envelope.
        ---- LLLL  Channel C Level.
    R11 PPPP PPPP  Envelope period  7..0.
    R12 PPPP PPPP  Envelope period 15..8.
    R13 ---- C---  Envelope shape "Continue" control.
        ---- -A--  Envelope shape "Attack" control.
        ---- --A-  Envelope shape "Alternate" control.
        ---- ---H  Envelope shape "Hold" control.
    R14 DDDD DDDD  unused
    R15 DDDD DDDD  unused

The tone period numbers must be calculated for a 2.00 MHz clock frequency of the PSG:

Tone_frequency = 2 MHz / (16 * period)


Sound - ZX Spectrum mode
------------------------

Instead of using the PSG, you can use the 1-bit ZX-Spectrum sound mode. This mode is
switched-on by writing 1 to port_out_sound_mode.

port_out_sound_mode equ 0x43 ; port number to switch to ZX spectrum sound mode

The speaker can now be controlled by writing to port_io_zx_spectrum. Bit3 and bit4 will
be written to the speaker, amplitude of bit4 is 3 times that of bit3.

port_io_zx_spectrum = 0xFE   // compatible with ZX spectrum


Chapter 5  Debugger support
---------------------------

Isetta has support for a debugger. The programmer has to provide the debugger code (Z80).
The debugger code must be somewhere in the range 0x8000 - 0xFFFF. Let's call the MSB of
the debugger code 0xMM

When the debugger is switched on, the following will happen:

- at each CALL, the debugger code will be called at address 0xMM20.
- at each RET,  the debugger code will be called at address 0xMM28. 

The debugger can be switched ON by writing 0xMM to the debugger control port:

port_out_dbg = 0x1A;

It can be switched OFF by writing a 0x00 value to this port.



NOTE A conditional CALL or RET will not trigger the debugger if the condition is not satisfied. A RETI
     will not trigger the debugger.

NOTE The debugger support is only for Z80 code.


Debugger example code for RET instructions
------------------------------------------

We start with the RET instructions, these are simplest.

The debugger must define a location where the PC is stored, let's use 0x1234 as example.
In this example, we will place our debugging code starting at 0xD000.

The first thing in the debugging code, is to store the PC to 0x1234. After encountering 
the RET instruction, the microcode will save the PC in two internal registers (reg_th and
reg_tl). These registers can also be used by scanline interrupts, but between the RET 
instruction and the first debugging instruction, scanline interrupts are blocked.

The next thing is obtaining the return address, and write it into the JP instruction at the end.

The next thing to do, is disable debugging. We don't want that a CALL or RET inside the
debugger again calls the debugger. We need the ACC, so we first save it to stack with a push.

addr   instruction
----   -----------
D028   ED 7F 34 12  ; store saved PC at 0x1234

       E3           ex (sp),hl  ; get return address, while saving HL
       22 .. ..     ld (dbg_ra+1),hl ; store return address in the JP instruction
       E1           pop hl  ; restore HL

       F5           push AF
       AF           xor A
       D3 1A        out (0x1A),a  ; debugging off

       ; here you can place code for displaying registers, return address, etc.
       ; it can also display the saved PC (available at 0x1234)
                    push hl
                    ld hl,(0x1234) ; get saved pc. (This is the address after the RET)
                    dec hl 
                    ; can now display HL (address of the RET instruction)
                    pop hl
       ; after this code, we must switch the debugger ON again 
       ; and perform the actual RET instruction

       3E D0        ld a,0xD0     ; MSB of the debugging code
       D3 1A        out (0x1A),a  ; debugging ON again
       ED 6B        ei2
       F1           pop AF

dbg_ra:C3 .. ..     jp xxxx   ; self-modifying code


NOTE If you use a RST #38 interrupt, debugging mode should be switched OFF at the 
beginning of the interrupt code, and switched ON again at the end, otherwise your debugger
will also show every call and ret that occurs during the interrupt. Note that at the 
end of the interrupt, you should not use a RET instruction (that would immediately trigger
 a new debugger call). But you can use RETI.

NOTE The interrupt system has a second set of enable/disable instructions, called EI2 and DI2.
This set can be used independently from the normal EI and DI. Interrupts can only occur if 
both EI and EI2 are valid. The ED 7F instruction, that stores the saved PC, will also do a DI2.
  DI2 instruction:  ED 63 
  EI2 instruction:  ED 6B
The EI2/DI2 set is intended to be used where you want to disable interrupts, but you don't 
know if interrupts were already disabled with DI.

NOTE Scanline interrupts are not disabled by the DI or DI2 instruction. But scanline interrupts
do not change the Z80 state (They don't use the stack or any other Z80 registers).


Debugger example code for CALL instructions
-------------------------------------------

This is similar to the RET code.

addr   instruction
----   -----------
D020   ED 7F 34 12  ; store saved PC at 0x1234
       18 ..        JR dbg_1 ; jump over the RET code at 0xD028                    

dbg_1: F5           push AF
       AF           xor A
       D3 1A        out (0x1A),a  ; debugging off
       ; here you can place code for displaying registers, call address, etc.
       ; it can also display the saved PC (available at 0x1234)
                    push hl
                    push de
                    ld hl,(0x1234) ; get saved pc. (This is the address after the call)
                    dec hl 
                    ld d,(hl) ; msb of call addr
                    dec hl
                    ld e,(hl) ; lsb of call addr
                    dec hl
                    ld (dbg_ca+1),de   ; store called address (must ALWAYS be done)

                    ; can now display HL (address of the CALL instruction)
                    ; and display DE (destination of the CALL) 

                    pop de
                    pop hl
       ; after this code, we must switch the debugger ON again 
       ; and perform the actual CALL instruction

       3E D0        ld a,0xD0     ; MSB of the debugging code
       D3 1A        out (0x1A),a  ; debugging ON again
       F1           pop AF

                    push hl  ;  save HL
       2A 34 12     ld hl,(0x1234) ; get saved pc. This is the return address.

       E3           ex (sp),hl  ; put return address on stack , while restoring HL
       ED 6B        ei2

dbg_ca:C3 .. ..     jp xxxx   ; self-modifying code. JP to the destination address




end.
----





